using System;
using System.Threading;
using FluentNHibernate.Cfg;
using NHibernate;
using NHibernate.Cfg;
using NHibernateInsight.Tests.Infrastructure.Data;

namespace NHibernateInsight.Tests.Infrastructure
{
    public class TestContext
    {
        private IDatabaseUsageStrategy _currentlyUsedStrategy;
        private bool _onInitCreateDb = true;
        private bool _onInitCreateSchema = true;
        private bool _onCleanupDropDb = true;
        private bool _onCleanupDropSchema = true;


        protected void Output(string message)
        {
            Console.WriteLine(message);
        }
        protected void Output(string messageTemplate, params object[] parameters)
        {
            Console.WriteLine(string.Format(messageTemplate, parameters));
        }
        protected void DontCreateDbOnInit()
        {
            _onInitCreateDb = false;
        }
        protected void DontCreateSchemaOnInit()
        {
            _onInitCreateSchema = false;
        }
        protected void DontDropDbOnCleanup()
        {
            _onCleanupDropDb = false;
        }
        protected void DontDropSchemaOnCleanup()
        {
            _onCleanupDropSchema = false;
        }
        protected void HideCreateAndDropDbSqlFromConsole()
        {
            _WarnWhenStrategyNotConfigured();

            _currentlyUsedStrategy.HideCreateAndDropDbSql = true;
        }
        protected void HideCreateAndDropSchemaSqlFromConsole()
        {
            _WarnWhenStrategyNotConfigured();

            _currentlyUsedStrategy.HideCreateAndDropSchemaSql = true;
        }

        protected void PrepareForSql2005Db()
        {
            _currentlyUsedStrategy = new Sql2005DatabaseUsageStrategy(_DefaultDatabaseName());
        }
        protected void PrepareForSql2005ExpressDb()
        {
            _currentlyUsedStrategy = new Sql2005ExpressDatabaseUsageStrategy(_DefaultDatabaseName());
        }
        protected void PrepareForSqlLiteDb()
        {
            _currentlyUsedStrategy = new SqlLiteDatabaseUsageStrategy();
        }

        protected void PrepareDatabaseMedia()
        {
            _currentlyUsedStrategy.PrepareDatabaseMedia();
        }
        protected void ReCreateDatabaseSchema()
        {
            _currentlyUsedStrategy.ReCreateDatabaseSchema();
        }
        protected void Init(Action<MappingConfiguration> mappings)
        {
            if (_currentlyUsedStrategy == null) throw new ArgumentException("Please run one of the 'PrepareFor...Db' methods to setup database!");


            if (_onInitCreateDb) PrepareDatabaseMedia();

            _currentlyUsedStrategy.Init(mappings);

            if (_onInitCreateSchema) ReCreateDatabaseSchema();
        }
        protected void Cleanup()
        {
            _WarnWhenStrategyNotConfigured();

            if (_onInitCreateSchema && _onCleanupDropSchema) _currentlyUsedStrategy.DropSchema();

            _currentlyUsedStrategy.CleanupResources();

            Thread.Sleep(5000);

            if (_onInitCreateDb && _onCleanupDropDb) _currentlyUsedStrategy.DropDatabaseMedia();
        }

        protected ISession CurrentSession
        {
            get
            {
                _WarnWhenStrategyNotConfigured();

                return _currentlyUsedStrategy.CurrentSession;
            }
        }
        protected Configuration CurrentConfiguration
        {
            get
            {
                _WarnWhenStrategyNotConfigured();

                return _currentlyUsedStrategy.CurrentConfiguration;
            }
        }



        private void _WarnWhenStrategyNotConfigured()
        {
            if (_currentlyUsedStrategy == null) throw new ArgumentException("Please run one of the 'PrepareFor...Db' methods to setup database! Afterwards run Init() to initialize it!");
        }
        private string _DefaultDatabaseName()
        {
            var assemblyName = this.GetType().Assembly.GetName().Name;
            return assemblyName.Replace(".", "_");
        }
    }
}